package gitobject;



import repository.Repository;
import sha1.SHA1;

import zlib.ZLibUtils;
import fileoperation.FileReader;

import java.io.*;
import java.lang.reflect.Array;
import java.security.MessageDigest;
import java.util.*;


public class Tree extends GitObject{
    protected ArrayList<GitObject> treeList = new ArrayList<>();	//GitObjects in tree
    //可变列表储存文件夹中所有元素，包括子文件夹名和文件名
    protected ArrayList<String> treeStringList;
    public Tree(){}
    public ArrayList<GitObject> getTreeList(){ return treeList;}
    /**
     * Constructor
     */
    public Tree(File file) throws Exception {
        this.file = file;
        String content = "";
        List<File> fs = new ArrayList<File>();
        dfsFile(file,fs);
        //此处可调用FileCreation.recoverWorkTree()函数
   //     fs = sortFile(fs);
            for(int i=0 ; i < fs.size() ; i++){
                if(fs.get(i).isFile()){
                    Blob blob = new Blob(fs.get(i));
                    treeList.add(blob);
                    content = content.concat("100644 blob " + blob.getKey() + " " + fs.get(i).getName() + "\n");
                }
                else if(fs.get(i).isDirectory()){
                    content = content.concat("040000 tree " + new Tree(fs.get(i)).getKey() + " " + fs.get(i).getName() + "\n");
                }
        }
        this.treeList = new ArrayList<>();
        this.fmt = "tree";
        this.mode = "040000";//04表示文件夹，git中所有文件夹默认可读可写
        this.value = content;
        this.key = SHA1.getHash( content );
//     // compressWrite();
        writeObject();
    }

    public ArrayList<String> getTreeStringList(){
        List<File> fs = new ArrayList<File>();
        try{
            this.treeStringList = FileReader.readByBufferReader(this.value);
        }catch (Exception e){
            e.printStackTrace();
        }

        return treeStringList;
    }

    /**
     * Deserialize a tree object with treeId and its path.
     * 树的反序列化.后序恢复工作区中文件时需要调用FileCreation
     */

    public Tree (String Id) throws IOException {
        this.fmt = "tree";
        this.mode = "040000";
        try{
            File file = new File(path + File.separator + Id);
            if(file.exists()){
                this.key = Id ;
                ObjectInputStream oos = new ObjectInputStream(new FileInputStream(file));
                this.value = (String)oos.readObject();
                //反序列化生成blob的value值
                this.file = new File(Repository.getWorkTree() + File.separator + Id);
                getTreeList();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * Depth First Search the files .
     * You should consider whether it's a file or a directory.
     * @return List
     */
    public static void dfsFile(File file,List list){
        File[] fs = file.listFiles();
        for(File f:fs){
            if(f.isDirectory()){
                dfsFile(f,list);//是文件夹则继续递归
                list.add(f);//子文件夹添加到list

            }
            if(f.isFile()){
                list.add(f);//文件添加到list
            }
        }
    }

    /**
     * Sort the files in a certain order. You should consider whether it's a file or a directory.
     * @return List
     */
    public static File[]  sortFile(File[] fs){
        Arrays.sort(fs, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2)
            {
                if (o1.isDirectory() && o2.isFile())
                    return 1;
                if (o1.isFile() && o2.isDirectory())
                    return -1;
                return o1.getName().compareTo(o2.getName());
            }
        });
        return fs;
    }

    /**
     * Generate the key of a tree object.
     * @return String
     */

    public String genKey(String value) throws Exception{
        try{
            key = SHA1.getHash(value);//调用工具类中自定义的getDirHash()函数
        }catch (Exception e){
            e.printStackTrace();
        }
        return key;
    }

    @Override
    public String toString(){ return "040000 tree " + key + " " + this.file.getName();}

}
